#pragma once
#include <iostream>
#include <string>
#include <vector>
#include <cstdarg>
#include <fstream>
#include <ctime>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
using namespace std;

enum { // 日志等级
    Debug = 0,
    Info,
    Warning,
    Error,
    Fatal
};

enum { // 打印类别
    Screen = 10, // 向显示器打印
    OneFile, // 向一个文件中打印
    ClassFile // 分类向不同的文件中写入
};


const int default_style = Screen; // 缺省的打印模式
const string default_filename = "Log.";
const string default_logdir = "log";



class Log {
    public :
    Log() 
        :_style(default_style)
        ,_filename(default_filename)
    {
        Level = { "Debug", "Info", "Warning", "Error", "Fatal", "Unknown" };
        mkdir(default_logdir.c_str(), 0775);
    }

    void Enable(int sty) { // 调整打印模式
        _style = sty;
    }

    // 将时间戳转化成年月日时分秒形式的字符串
    string TimeStampToLocalTime() {
        time_t currtime = time(nullptr);
        struct tm *curr = localtime(&currtime);
        char time_buffer[128];
        snprintf(time_buffer, sizeof(time_buffer), "%d-%d-%d %d:%d:%d",\
        curr->tm_year + 1900, curr->tm_mon + 1, curr->tm_mday,\
        curr->tm_hour, curr->tm_min, curr->tm_sec);
        return time_buffer;
    }

    void WriteLogToOneFile(const string& log_name, const string& LogInfo) {
        // 向文件中写入
        umask(0);
        int fd = open(log_name.c_str(), O_CREAT | O_APPEND | O_WRONLY, 0666);
        if (fd < 0) {
            return;
        }
        write(fd, LogInfo.c_str(), LogInfo.size());

        close(fd);

        // ofstream out(log_name);
        // if (!out.is_open()) {
        //     return;
        // }
        // out.write(LogInfo.c_str(), LogInfo.size());
        // out.close();



    }


    void WriteLogToClassFile(const string level, const string& LogInfo) {
        string log_name = _filename;
        log_name += level; // 日志文件名称加上后缀
        log_name = default_logdir + "/" + log_name;
        WriteLogToOneFile(log_name, LogInfo);
    }



    void WriteLog(int level, const string& LogInfo) {
        switch (_style) {
            case Screen :
            cout << LogInfo << endl;
                break;
            case OneFile : 
                WriteLogToClassFile("all", LogInfo);
                break;
            case ClassFile :
                WriteLogToClassFile(Level[level], LogInfo);
                break;
            default :
                break;
        }
    }
    void LogMessage(int level, const char* format, ...) { // 日志接口
        va_list args;
        char rightbuffer[1024];

        va_start(args, format);
        // args指向了可变参数部分
        vsnprintf(rightbuffer, sizeof(rightbuffer), format, args);
        va_end(args); // args = nullptr
        // uint64_t currtime = time(nullptr);
        // printf("[%s][%s]%s\n", Level[level].c_str(), to_string(currtime).c_str(), left);

        // 将时间戳转化成年月日时分秒的形式
        // printf("[%s][%s], %s\n", Level[level].c_str(), TimeStampToLocalTime().c_str(), left);

        char leftbuffer[1024];
        snprintf(leftbuffer, sizeof(leftbuffer), "[%s][%s][%s] ", to_string(getpid()).c_str(), \
                                            Level[level].c_str(), TimeStampToLocalTime().c_str());
        // printf("%s: %s\n", leftbuffer, rightbuffer);

        string LogInfo = leftbuffer;
        LogInfo += rightbuffer;

        WriteLog(level, LogInfo);
         
    }
    ~Log() {

    }
    private :
    vector<string> Level;
    int _style; // 打印的模式
    string _filename; // 文件名

};


// 配置中心
Log lg;
class Conf {
    public :
    Conf() {
        lg.Enable(Screen);
    }
    ~Conf() {
         
    }
    private :

};

Conf conf;